﻿using AutoMapper;
using Spark.Config.Api.AppCode;
using Spark.Config.Api.AppCode.Sms;
using Spark.Config.Api.DTO.Sms;
using Spark.Config.Api.Entity;
using Spark.Config.Api.Repository;
using Spark.Config.Api.Services.Abstractions;
using Spark.Core.Exceptions;
using Spark.Core.Values;
using System;

namespace Spark.Config.Api.Services.Implements
{
    public class SmsServices : ISmsServices
    {
        #region Constructor

        private readonly ISmsRepository _smsRepository;
        private readonly IAppRepository _appRepository;
        private readonly Func<string, ISms> _smsFactory;
        private readonly IPower _power;
        private readonly IMapper _mapper;

        #endregion Constructor

        #region Constructor

        public SmsServices(ISmsRepository smsRepository
            , IAppRepository appRepository
            , Func<string, ISms> smsFactory
            , IPower power
            , IMapper mapper)
        {
            _smsRepository = smsRepository;
            _appRepository = appRepository;
            _smsFactory = smsFactory;
            _power = power;
            _mapper = mapper;
        }

        #endregion Constructor

        #region Query

        public QueryPageResponse<SmsTempResponse> LoadTempList(SmsTempSearchRequest request)
        {
            request.IsAdmin = _power.IsAdmin;
            request.UserId = _power.UserId;
            return _smsRepository.GetTempList(request);
        }

        public QueryPageResponse<SmsRecordResponse> LoadRecordList(SmsRecordSearchRequest request)
        {
            request.IsAdmin = _power.IsAdmin;
            request.UserId = _power.UserId;
            return _smsRepository.GetRecordList(request);
        }

        public QueryPageResponse<SmsProviderResponse> LoadProviderList(SmsProviderSearchRequest request)
        {
            if (_power.IsAdmin == 0)
                return default(QueryPageResponse<SmsProviderResponse>);
            return _smsRepository.GetProviderList(request);
        }

        #endregion Query

        #region 短信操作

        public void Send(SendRequest request)
        {
            var app = _appRepository.GetEntity(new { request.AppCode });
            if (app == null)
                throw new SparkException("项目编码有误！");

            SmsRecord record = new SmsRecord();
            record.Content = request.Content;
            record.Mobile = request.Mobile;
            record.AppId = app.Id;
            record.AppCode = app.Code;

            //数据库插入短信记录
            record.Id = _smsRepository.InsertRecord(record);

            ChannelSend(record);
        }

        public void Send(SendByTempRequest request)
        {
            var app = _appRepository.GetEntity(new { request.AppCode });
            if (app == null)
                throw new SparkException("项目编码有误！");

            //获取模板内容
            var temp = _smsRepository.GetTemp(new { request.TempId });
            if (temp == null)
                throw new SparkException("模板不存在！");

            if (request.Parameters != null && request.Parameters.Count > 0)
            {
                foreach (var para in request.Parameters)
                {
                    temp.Content = temp.Content.Replace("{" + para.Key + "}", para.Value);
                }
            }

            SmsRecord record = new SmsRecord();
            record.Content = temp.Content;
            record.Mobile = request.Mobile;
            record.TempId = request.TempId;
            record.AppId = app.Id;
            record.AppCode = app.Code;

            //数据库插入短信记录
            record.Id = _smsRepository.InsertRecord(record);

            //发送消息
            ChannelSend(record);
        }

        public void SaveTemp(SmsTempRequest request)
        {
            var app = _appRepository.GetEntity(new { request.AppCode });
            if (app == null)
                throw new SparkException("项目有误！");

            if (request.Id == 0)
            {
                var smsTemp = _mapper.Map<SmsTemp>(request);
                smsTemp.AppId = app.Id;
                _smsRepository.InsertTemp(smsTemp);
            }
            else
            {
                _smsRepository.UpdateTemp(
                    new
                    {
                        AppId = app.Id,
                        AppCode = app.Code,
                        request.Id,
                        request.TempId,
                        request.Name,
                        request.Status,
                        request.Content,
                        UpdateTime = DateTime.Now
                    });
            }
        }

        public void SaveProvider(SmsProviderRequest request)
        {
            if (_power.IsAdmin == 1)
            {
                if (request.Id == 0)
                {
                    _smsRepository.InsertProvider(_mapper.Map<SmsProvider>(request));
                }
                else
                {
                    _smsRepository.UpdateProvider(
                        new
                        {
                            request.Id,
                            request.Name,
                            request.Status,
                            request.Code,
                            UpdateTime = DateTime.Now
                        });
                }
            }
        }

        private void ChannelSend(SmsRecord record)
        {
            //重试次数
            var i = 0;
            while (i < 3)
            {
                //获取可用渠道
                var provider = _smsRepository.GetProvider(new { Status = 1 });
                if (provider == null)
                    throw new SparkException("暂无可用的短信服务商！");

                var smsProvider = _smsFactory(provider.Code);
                var flag = smsProvider.Send(record.Mobile, record.Content);
                if (flag)
                {
                    //修改为成功
                    record.Status = (int)SmsStatus.Success;
                    _smsRepository.UpdateRecord(
                        new
                        {
                            UpdateTime = DateTime.Now,
                            record.Id,
                            Provider = provider.Id,
                            record.Status
                        });
                    //成功则退出
                    break;
                }
                else
                {
                    i++;
                    //最后一次失败保存失败信息
                    if (i >= 3)
                    {
                        record.Status = (int)SmsStatus.Failure;
                        _smsRepository.UpdateRecord(
                            new
                            {
                                UpdateTime = DateTime.Now,
                                record.Id,
                                Provider = provider.Id,
                                record.Status
                            });
                    }
                }
            }
        }

        #endregion 短信操作
    }
}